/**
 * Copyright (c) Tiny Technologies, Inc. All rights reserved.
 * Licensed under the LGPL or a commercial license.
 * For LGPL see License.txt in the project root for license information.
 * For commercial licenses see https://www.tiny.cloud/
 *
 * Version: 5.2.0 (2020-02-13)
 */
import tinymce from 'tinymce/tinymce'
(function (domGlobals) {
	'use strict'

	var global$1 = tinymce.util.Tools.resolve('tinymce.PluginManager')

	var noop = function () {
	}
	var constant = function (value) {
		return function () {
			return value
		}
	}
	var identity = function (x) {
		return x
	}
	var die = function (msg) {
		return function () {
			throw new Error(msg)
		}
	}
	var never = constant(false)
	var always = constant(true)

	var none = function () {
		return NONE
	}
	var NONE = (function () {
		var eq = function (o) {
			return o.isNone()
		}
		var call = function (thunk) {
			return thunk()
		}
		var id = function (n) {
			return n
		}
		var me = {
			fold: function (n, s) {
				console.log(s)
				return n()
			},
			is: never,
			isSome: never,
			isNone: always,
			getOr: id,
			getOrThunk: call,
			getOrDie: function (msg) {
				throw new Error(msg || 'error: getOrDie called on none.')
			},
			getOrNull: constant(null),
			getOrUndefined: constant(undefined),
			or: id,
			orThunk: call,
			map: none,
			each: noop,
			bind: none,
			exists: never,
			forall: always,
			filter: none,
			equals: eq,
			equals_: eq,
			toArray: function () {
				return []
			},
			toString: constant('none()')
		}
		if (Object.freeze) {
			Object.freeze(me)
		}
		return me
	}())
	var some = function (a) {
		var constant_a = constant(a)
		var self = function () {
			return me
		}
		var bind = function (f) {
			return f(a)
		}
		var me = {
			fold: function (n, s) {
				return s(a)
			},
			is: function (v) {
				return a === v
			},
			isSome: always,
			isNone: never,
			getOr: constant_a,
			getOrThunk: constant_a,
			getOrDie: constant_a,
			getOrNull: constant_a,
			getOrUndefined: constant_a,
			or: self,
			orThunk: self,
			map: function (f) {
				return some(f(a))
			},
			each: function (f) {
				f(a)
			},
			bind: bind,
			exists: bind,
			forall: bind,
			filter: function (f) {
				return f(a) ? me : NONE
			},
			toArray: function () {
				return [a]
			},
			toString: function () {
				return 'some(' + a + ')'
			},
			equals: function (o) {
				return o.is(a)
			},
			equals_: function (o, elementEq) {
				return o.fold(never, function (b) {
					return elementEq(a, b)
				})
			}
		}
		return me
	}
	var from = function (value) {
		return value === null || value === undefined ? NONE : some(value)
	}
	var Option = {
		some: some,
		none: none,
		from: from
	}

	var typeOf = function (x) {
		if (x === null) {
			return 'null'
		}
		var t = typeof x
		if (t === 'object' && (Object.prototype.isPrototypeOf.call(Array.prototype, x) || (x.constructor && x.constructor.name === 'Array'))) {
			return 'array';
		}
		if (t === 'object' && (Object.prototype.isPrototypeOf.call(String.prototype, x) || (x.constructor && x.constructor.name === 'String'))) {
			return 'string';
		}
		return t
	}
	var isType = function (type) {
		return function (value) {
			return typeOf(value) === type
		}
	}
	var isString = isType('string')
	var isObject = isType('object')
	var isArray = isType('array')
	var isBoolean = isType('boolean')
	var isFunction = isType('function')
	var isNumber = isType('number')

	var nativeSlice = Array.prototype.slice
	var nativePush = Array.prototype.push
	var each = function (xs, f) {
		for (var i = 0, len = xs.length; i < len; i++) {
			var x = xs[i]
			f(x, i)
		}
	}
	var flatten = function (xs) {
		var r = []
		for (var i = 0, len = xs.length; i < len; ++i) {
			if (!isArray(xs[i])) {
				throw new Error('Arr.flatten item ' + i + ' was not an array, input: ' + xs)
			}
			nativePush.apply(r, xs[i])
		}
		return r
	}
	var head = function (xs) {
		return xs.length === 0 ? Option.none() : Option.some(xs[0])
	}
	var from$1 = isFunction(Array.from) ? Array.from : function (x) {
		return nativeSlice.call(x)
	}
	console.log(from$1)
	var findMap = function (arr, f) {
		for (var i = 0; i < arr.length; i++) {
			var r = f(arr[i], i)
			if (r.isSome()) {
				return r
			}
		}
		return Option.none()
	}

	var __assign = function () {
		__assign = Object.assign || function __assign(t) {
			for (var s, i = 1, n = arguments.length; i < n; i++) {
				s = arguments[i]
				for (var p in s) {
					if (Object.prototype.hasOwnProperty.call(s, p)) {
						t[p] = s[p]
					}
				}
			}
			return t
		}
		return __assign.apply(this, arguments)
	}

	var exports$1 = {};
	var module = {exports: exports$1};
	(function (define, exports, module, require) {
		(function (f) {
			if (typeof exports === 'object' && typeof module !== 'undefined') {
				module.exports = f()
			} else if (typeof define === 'function' && define.amd) {
				define([], f)
			} else {
				var g
				if (typeof window !== 'undefined') {
					g = window
				} else if (typeof global !== 'undefined') {
					g = global
				} else if (typeof self !== 'undefined') {
					g = self
				} else {
					g = this
				}
				g.EphoxContactWrapper = f()
			}
		}(function () {
			return (function () {
				function r(e, n, t) {
					function o(i, f) {
						if (!n[i]) {
							if (!e[i]) {
								var c = typeof require == 'function' && require
								if (!f && c) {
									return c(i, !0)
								}
								if (u) {
									return u(i, !0)
								}
								var a = new Error('Cannot find module \'' + i + '\'')
								throw a.code = 'MODULE_NOT_FOUND', a
							}
							var p = n[i] = {exports: {}}
							e[i][0].call(p.exports, function (r) {
								var n = e[i][1][r]
								return o(n || r)
							}, p, p.exports, r, e, n, t)
						}
						return n[i].exports
					}

					for (var u = typeof require == 'function' && require, i = 0; i < t.length; i++) {
						o(t[i])
					}
					return o
				}

				return r
			}())({
				1: [
					function (require, module, exports) {
						console.log(exports)
						var process = module.exports = {}
						var cachedSetTimeout
						var cachedClearTimeout

						function defaultSetTimout() {
							throw new Error('setTimeout has not been defined')
						}

						function defaultClearTimeout() {
							throw new Error('clearTimeout has not been defined')
						}

						(function () {
							try {
								if (typeof setTimeout === 'function') {
									cachedSetTimeout = setTimeout
								} else {
									cachedSetTimeout = defaultSetTimout
								}
							} catch (e) {
								cachedSetTimeout = defaultSetTimout
							}
							try {
								if (typeof clearTimeout === 'function') {
									cachedClearTimeout = clearTimeout
								} else {
									cachedClearTimeout = defaultClearTimeout
								}
							} catch (e) {
								cachedClearTimeout = defaultClearTimeout
							}
						}())

						function runTimeout(fun) {
							if (cachedSetTimeout === setTimeout) {
								return setTimeout(fun, 0)
							}
							if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
								cachedSetTimeout = setTimeout
								return setTimeout(fun, 0)
							}
							try {
								return cachedSetTimeout(fun, 0)
							} catch (e) {
								try {
									return cachedSetTimeout.call(null, fun, 0)
								} catch (e) {
									return cachedSetTimeout.call(this, fun, 0)
								}
							}
						}

						function runClearTimeout(marker) {
							if (cachedClearTimeout === clearTimeout) {
								return clearTimeout(marker)
							}
							if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
								cachedClearTimeout = clearTimeout
								return clearTimeout(marker)
							}
							try {
								return cachedClearTimeout(marker)
							} catch (e) {
								try {
									return cachedClearTimeout.call(null, marker)
								} catch (e) {
									return cachedClearTimeout.call(this, marker)
								}
							}
						}

						var queue = []
						var draining = false
						var currentQueue
						var queueIndex = -1

						function cleanUpNextTick() {
							if (!draining || !currentQueue) {
								return
							}
							draining = false
							if (currentQueue.length) {
								queue = currentQueue.concat(queue)
							} else {
								queueIndex = -1
							}
							if (queue.length) {
								drainQueue()
							}
						}

						function drainQueue() {
							if (draining) {
								return
							}
							var timeout = runTimeout(cleanUpNextTick)
							draining = true
							var len = queue.length
							while (len) {
								currentQueue = queue
								queue = []
								while (++queueIndex < len) {
									if (currentQueue) {
										currentQueue[queueIndex].run()
									}
								}
								queueIndex = -1
								len = queue.length
							}
							currentQueue = null
							draining = false
							runClearTimeout(timeout)
						}

						process.nextTick = function (fun) {
							var args = new Array(arguments.length - 1)
							if (arguments.length > 1) {
								for (var i = 1; i < arguments.length; i++) {
									args[i - 1] = arguments[i]
								}
							}
							queue.push(new Item(fun, args))
							if (queue.length === 1 && !draining) {
								runTimeout(drainQueue)
							}
						}

						function Item(fun, array) {
							this.fun = fun
							this.array = array
						}

						Item.prototype.run = function () {
							this.fun.apply(null, this.array)
						}
						process.title = 'browser'
						process.browser = true
						process.env = {}
						process.argv = []
						process.version = ''
						process.versions = {}

						function noop() {
						}

						process.on = noop
						process.addListener = noop
						process.once = noop
						process.off = noop
						process.removeListener = noop
						process.removeAllListeners = noop
						process.emit = noop
						process.prependListener = noop
						process.prependOnceListener = noop
						process.listeners = function (name) {
							console.log(name)
							return []
						}
						process.binding = function (name) {
							console.log(name)
							throw new Error('process.binding is not supported')
						}
						process.cwd = function () {
							return '/'
						}
						process.chdir = function (dir) {
							console.log(dir)
							throw new Error('process.chdir is not supported')
						}
						process.umask = function () {
							return 0
						}
					},
					{}
				],
				2: [
					function (require, module, exports) {
						(function (setImmediate) {
							(function (root) {
								console.log(exports)
								var setTimeoutFunc = setTimeout

								function noop() {
								}

								function bind(fn, thisArg) {
									return function () {
										fn.apply(thisArg, arguments)
									}
								}

								function Promise(fn) {
									if (typeof this !== 'object') {
										throw new TypeError('Promises must be constructed via new')
									}
									if (typeof fn !== 'function') {
										throw new TypeError('not a function')
									}
									this._state = 0
									this._handled = false
									this._value = undefined
									this._deferreds = []
									doResolve(fn, this)
								}

								function handle(self, deferred) {
									while (self._state === 3) {
										self = self._value
									}
									if (self._state === 0) {
										self._deferreds.push(deferred)
										return
									}
									self._handled = true
									Promise._immediateFn(function () {
										var cb = self._state === 1 ? deferred.onFulfilled : deferred.onRejected
										if (cb === null) {
											(self._state === 1 ? resolve : reject)(deferred.promise, self._value)
											return
										}
										var ret
										try {
											ret = cb(self._value)
										} catch (e) {
											reject(deferred.promise, e)
											return
										}
										resolve(deferred.promise, ret)
									})
								}

								function resolve(self, newValue) {
									try {
										if (newValue === self) {
											throw new TypeError('A promise cannot be resolved with itself.')
										}
										if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) {
											var then = newValue.then
											if (newValue instanceof Promise) {
												self._state = 3
												self._value = newValue
												finale(self)
												return
											} else if (typeof then === 'function') {
												doResolve(bind(then, newValue), self)
												return
											}
										}
										self._state = 1
										self._value = newValue
										finale(self)
									} catch (e) {
										reject(self, e)
									}
								}

								function reject(self, newValue) {
									self._state = 2
									self._value = newValue
									finale(self)
								}

								function finale(self) {
									if (self._state === 2 && self._deferreds.length === 0) {
										Promise._immediateFn(function () {
											if (!self._handled) {
												Promise._unhandledRejectionFn(self._value)
											}
										})
									}
									for (var i = 0, len = self._deferreds.length; i < len; i++) {
										handle(self, self._deferreds[i])
									}
									self._deferreds = null
								}

								function Handler(onFulfilled, onRejected, promise) {
									this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null
									this.onRejected = typeof onRejected === 'function' ? onRejected : null
									this.promise = promise
								}

								function doResolve(fn, self) {
									var done = false
									try {
										fn(function (value) {
											if (done) {
												return
											}
											done = true
											resolve(self, value)
										}, function (reason) {
											if (done) {
												return
											}
											done = true
											reject(self, reason)
										})
									} catch (ex) {
										if (done) {
											return
										}
										done = true
										reject(self, ex)
									}
								}

								Promise.prototype['catch'] = function (onRejected) {
									return this.then(null, onRejected)
								}
								Promise.prototype.then = function (onFulfilled, onRejected) {
									var prom = new this.constructor(noop)
									handle(this, new Handler(onFulfilled, onRejected, prom))
									return prom
								}
								Promise.all = function (arr) {
									var args = Array.prototype.slice.call(arr)
									return new Promise(function (resolve, reject) {
										if (args.length === 0) {
											return resolve([])
										}
										var remaining = args.length

										function res(i, val) {
											try {
												if (val && (typeof val === 'object' || typeof val === 'function')) {
													var then = val.then
													if (typeof then === 'function') {
														then.call(val, function (val) {
															res(i, val)
														}, reject)
														return
													}
												}
												args[i] = val
												if (--remaining === 0) {
													resolve(args)
												}
											} catch (ex) {
												reject(ex)
											}
										}

										for (var i = 0; i < args.length; i++) {
											res(i, args[i])
										}
									})
								}
								Promise.resolve = function (value) {
									if (value && typeof value === 'object' && value.constructor === Promise) {
										return value
									}
									return new Promise(function (resolve) {
										resolve(value)
									})
								}
								Promise.reject = function (value) {
									return new Promise(function (resolve, reject) {
										reject(value)
									})
								}
								Promise.race = function (values) {
									return new Promise(function (resolve, reject) {
										for (var i = 0, len = values.length; i < len; i++) {
											values[i].then(resolve, reject)
										}
									})
								}
								Promise._immediateFn = typeof setImmediate === 'function' ? function (fn) {
									setImmediate(fn)
								} : function (fn) {
									setTimeoutFunc(fn, 0)
								}
								Promise._unhandledRejectionFn = function _unhandledRejectionFn(err) {
									if (typeof console !== 'undefined' && console) {
										console.warn('Possible Unhandled Promise Rejection:', err)
									}
								}
								Promise._setImmediateFn = function _setImmediateFn(fn) {
									Promise._immediateFn = fn
								}
								Promise._setUnhandledRejectionFn = function _setUnhandledRejectionFn(fn) {
									Promise._unhandledRejectionFn = fn
								}
								if (typeof module !== 'undefined' && module.exports) {
									module.exports = Promise
								} else if (!root.Promise) {
									root.Promise = Promise
								}
							}(this))
						}.call(this, require('timers').setImmediate))
					},
					{'timers': 3}
				],
				3: [
					function (require, module, exports) {
						(function (setImmediate, clearImmediate) {
							var nextTick = require('process/browser.js').nextTick
							var apply = Function.prototype.apply
							var slice = Array.prototype.slice
							var immediateIds = {}
							var nextImmediateId = 0
							exports.setTimeout = function () {
								return new Timeout(apply.call(setTimeout, window, arguments), clearTimeout)
							}
							exports.setInterval = function () {
								return new Timeout(apply.call(setInterval, window, arguments), clearInterval)
							}
							exports.clearTimeout = exports.clearInterval = function (timeout) {
								timeout.close()
							}

							function Timeout(id, clearFn) {
								this._id = id
								this._clearFn = clearFn
							}

							Timeout.prototype.unref = Timeout.prototype.ref = function () {
							}
							Timeout.prototype.close = function () {
								this._clearFn.call(window, this._id)
							}
							exports.enroll = function (item, msecs) {
								clearTimeout(item._idleTimeoutId)
								item._idleTimeout = msecs
							}
							exports.unenroll = function (item) {
								clearTimeout(item._idleTimeoutId)
								item._idleTimeout = -1
							}
							exports._unrefActive = exports.active = function (item) {
								clearTimeout(item._idleTimeoutId)
								var msecs = item._idleTimeout
								if (msecs >= 0) {
									item._idleTimeoutId = setTimeout(function onTimeout() {
										if (item._onTimeout) {
											item._onTimeout()
										}
									}, msecs)
								}
							}
							exports.setImmediate = typeof setImmediate === 'function' ? setImmediate : function (fn) {
								var id = nextImmediateId++
								var args = arguments.length < 2 ? false : slice.call(arguments, 1)
								immediateIds[id] = true
								nextTick(function onNextTick() {
									if (immediateIds[id]) {
										if (args) {
											fn.apply(null, args)
										} else {
											fn.call(null)
										}
										exports.clearImmediate(id)
									}
								})
								return id
							}
							exports.clearImmediate = typeof clearImmediate === 'function' ? clearImmediate : function (id) {
								delete immediateIds[id]
							}
						}.call(this, require('timers').setImmediate, require('timers').clearImmediate))
					},
					{
						'process/browser.js': 1,
						'timers': 3
					}
				],
				4: [
					function (require, module, exports) {
						console.log(exports)
						var promisePolyfill = require('promise-polyfill')
						var Global = (function () {
							if (typeof window !== 'undefined') {
								return window
							} else {
								return Function('return this;')()
							}
						}())
						module.exports = {boltExport: Global.Promise || promisePolyfill}
					},
					{'promise-polyfill': 2}
				]
			}, {}, [4])(4)
		}))
	}(undefined, exports$1, module, undefined))
	var Promise = module.exports.boltExport

	var nu = function (baseFn) {
		var data = Option.none()
		var callbacks = []
		var map = function (f) {
			return nu(function (nCallback) {
				get(function (data) {
					nCallback(f(data))
				})
			})
		}
		var get = function (nCallback) {
			if (isReady()) {
				call(nCallback)
			} else {
				callbacks.push(nCallback)
			}
		}
		var set = function (x) {
			data = Option.some(x)
			run(callbacks)
			callbacks = []
		}
		var isReady = function () {
			return data.isSome()
		}
		var run = function (cbs) {
			each(cbs, call)
		}
		var call = function (cb) {
			data.each(function (x) {
				domGlobals.setTimeout(function () {
					cb(x)
				}, 0)
			})
		}
		baseFn(set)
		return {
			get: get,
			map: map,
			isReady: isReady
		}
	}
	var pure = function (a) {
		return nu(function (callback) {
			callback(a)
		})
	}
	var LazyValue = {
		nu: nu,
		pure: pure
	}

	var errorReporter = function (err) {
		domGlobals.setTimeout(function () {
			throw err
		}, 0)
	}
	var make = function (run) {
		var get = function (callback) {
			run().then(callback, errorReporter)
		}
		var map = function (fab) {
			return make(function () {
				return run().then(fab)
			})
		}
		var bind = function (aFutureB) {
			return make(function () {
				return run().then(function (v) {
					return aFutureB(v).toPromise()
				})
			})
		}
		var anonBind = function (futureB) {
			return make(function () {
				return run().then(function () {
					return futureB.toPromise()
				})
			})
		}
		var toLazy = function () {
			return LazyValue.nu(get)
		}
		var toCached = function () {
			var cache = null
			return make(function () {
				if (cache === null) {
					cache = run()
				}
				return cache
			})
		}
		var toPromise = run
		return {
			map: map,
			bind: bind,
			anonBind: anonBind,
			toLazy: toLazy,
			toCached: toCached,
			toPromise: toPromise,
			get: get
		}
	}
	var nu$1 = function (baseFn) {
		return make(function () {
			return new Promise(baseFn)
		})
	}
	var pure$1 = function (a) {
		return make(function () {
			return Promise.resolve(a)
		})
	}
	var Future = {
		nu: nu$1,
		pure: pure$1
	}

	var value = function (o) {
		var is = function (v) {
			return o === v
		}
		var or = function (opt) {
			console.log(opt)
			return value(o)
		}
		var orThunk = function (f) {
			console.log(f)
			return value(o)
		}
		var map = function (f) {
			return value(f(o))
		}
		var mapError = function (f) {
			console.log(f)
			return value(o)
		}
		var each = function (f) {
			f(o)
		}
		var bind = function (f) {
			return f(o)
		}
		var fold = function (_, onValue) {
			return onValue(o)
		}
		var exists = function (f) {
			return f(o)
		}
		var forall = function (f) {
			return f(o)
		}
		var toOption = function () {
			return Option.some(o)
		}
		return {
			is: is,
			isValue: always,
			isError: never,
			getOr: constant(o),
			getOrThunk: constant(o),
			getOrDie: constant(o),
			or: or,
			orThunk: orThunk,
			fold: fold,
			map: map,
			mapError: mapError,
			each: each,
			bind: bind,
			exists: exists,
			forall: forall,
			toOption: toOption
		}
	}
	var error = function (message) {
		var getOrThunk = function (f) {
			return f()
		}
		var getOrDie = function () {
			return die(String(message))()
		}
		var or = function (opt) {
			return opt
		}
		var orThunk = function (f) {
			return f()
		}
		var map = function (f) {
			console.log(f)
			return error(message)
		}
		var mapError = function (f) {
			console.log(f)
			return error(f(message))
		}
		var bind = function (f) {
			console.log(f)
			return error(message)
		}
		var fold = function (onError, _) {
			console.log(_)
			return onError(message)
		}
		return {
			is: never,
			isValue: never,
			isError: always,
			getOr: identity,
			getOrThunk: getOrThunk,
			getOrDie: getOrDie,
			or: or,
			orThunk: orThunk,
			fold: fold,
			map: map,
			mapError: mapError,
			each: noop,
			bind: bind,
			exists: never,
			forall: always,
			toOption: Option.none
		}
	}
	var fromOption = function (opt, err) {
		return opt.fold(function () {
			return error(err)
		}, value)
	}
	var Result = {
		value: value,
		error: error,
		fromOption: fromOption
	}

	var wrap = function (delegate) {
		var toCached = function () {
			return wrap(delegate.toCached())
		}
		var bindFuture = function (f) {
			return wrap(delegate.bind(function (resA) {
				return resA.fold(function (err) {
					return Future.pure(Result.error(err))
				}, function (a) {
					return f(a)
				})
			}))
		}
		var bindResult = function (f) {
			return wrap(delegate.map(function (resA) {
				return resA.bind(f)
			}))
		}
		var mapResult = function (f) {
			return wrap(delegate.map(function (resA) {
				return resA.map(f)
			}))
		}
		var mapError = function (f) {
			return wrap(delegate.map(function (resA) {
				return resA.mapError(f)
			}))
		}
		var foldResult = function (whenError, whenValue) {
			return delegate.map(function (res) {
				return res.fold(whenError, whenValue)
			})
		}
		var withTimeout = function (timeout, errorThunk) {
			return wrap(Future.nu(function (callback) {
				var timedOut = false
				var timer = domGlobals.setTimeout(function () {
					timedOut = true
					callback(Result.error(errorThunk()))
				}, timeout)
				delegate.get(function (result) {
					if (!timedOut) {
						domGlobals.clearTimeout(timer)
						callback(result)
					}
				})
			}))
		}
		return __assign(__assign({}, delegate), {
			toCached: toCached,
			bindFuture: bindFuture,
			bindResult: bindResult,
			mapResult: mapResult,
			mapError: mapError,
			foldResult: foldResult,
			withTimeout: withTimeout
		})
	}
	var nu$2 = function (worker) {
		return wrap(Future.nu(worker))
	}
	var value$1 = function (value) {
		return wrap(Future.pure(Result.value(value)))
	}
	var error$1 = function (error) {
		return wrap(Future.pure(Result.error(error)))
	}
	var fromResult = function (result) {
		return wrap(Future.pure(result))
	}
	var fromFuture = function (future) {
		return wrap(future.map(Result.value))
	}
	var fromPromise = function (promise) {
		return nu$2(function (completer) {
			promise.then(function (value) {
				completer(Result.value(value))
			}, function (error) {
				completer(Result.error(error))
			})
		})
	}
	var FutureResult = {
		nu: nu$2,
		wrap: wrap,
		pure: value$1,
		value: value$1,
		error: error$1,
		fromResult: fromResult,
		fromFuture: fromFuture,
		fromPromise: fromPromise
	}

	var hasOwnProperty = Object.prototype.hasOwnProperty
	var deep = function (old, nu) {
		var bothObjects = isObject(old) && isObject(nu)
		return bothObjects ? deepMerge(old, nu) : nu
	}
	var baseMerge = function (merger) {
		return function () {
			var objects = new Array(arguments.length)
			for (var i = 0; i < objects.length; i++) {
				objects[i] = arguments[i]
			}
			if (objects.length === 0) {
				throw new Error('Can\'t merge zero objects')
			} else if (objects.length === 2) {
				// 默认第二条数据 并且具备 style 当做 api.getData() 的数据，增加 position: absolute;
				const twoObj = objects[1]
				if (Object.prototype.hasOwnProperty.call(twoObj, 'style')) {
					twoObj.style = `position: absolute;z-index: 1;left: auto; top: auto; ${twoObj.style}`;
				}
			}
			var ret = {}
			for (var j = 0; j < objects.length; j++) {
				var curObject = objects[j]
				for (var key in curObject) {
					if (hasOwnProperty.call(curObject, key)) {
						ret[key] = merger(ret[key], curObject[key])
					}
				}
			}
			return ret
		}
	}
	var deepMerge = baseMerge(deep)

	var ATTRIBUTE = domGlobals.Node.ATTRIBUTE_NODE
	var CDATA_SECTION = domGlobals.Node.CDATA_SECTION_NODE
	var COMMENT = domGlobals.Node.COMMENT_NODE
	var DOCUMENT = domGlobals.Node.DOCUMENT_NODE
	var DOCUMENT_TYPE = domGlobals.Node.DOCUMENT_TYPE_NODE
	var DOCUMENT_FRAGMENT = domGlobals.Node.DOCUMENT_FRAGMENT_NODE
	var ELEMENT = domGlobals.Node.ELEMENT_NODE
	var TEXT = domGlobals.Node.TEXT_NODE
	var PROCESSING_INSTRUCTION = domGlobals.Node.PROCESSING_INSTRUCTION_NODE
	var ENTITY_REFERENCE = domGlobals.Node.ENTITY_REFERENCE_NODE
	var ENTITY = domGlobals.Node.ENTITY_NODE
	var NOTATION = domGlobals.Node.NOTATION_NODE

	var Global = typeof domGlobals.window !== 'undefined' ? domGlobals.window : Function('return this;')()
	console.log(Global,NOTATION,ENTITY,ENTITY_REFERENCE,PROCESSING_INSTRUCTION,TEXT,ELEMENT,DOCUMENT_FRAGMENT,DOCUMENT_TYPE,DOCUMENT,COMMENT,CDATA_SECTION,ATTRIBUTE)
	// console.log(NOTATION)
	// console.log(ENTITY)
	// console.log(ENTITY_REFERENCE)
	// console.log(PROCESSING_INSTRUCTION)
	// console.log(TEXT)
	// console.log(ELEMENT)
	// console.log(DOCUMENT_FRAGMENT)
	// console.log(DOCUMENT_TYPE)
	// console.log(DOCUMENT)
	// console.log(COMMENT)
	// console.log(CDATA_SECTION)
	// console.log(ATTRIBUTE)

	var rawSet = function (dom, key, value) {
		if (isString(value) || isBoolean(value) || isNumber(value)) {
			dom.setAttribute(key, value + '')
		} else {
			domGlobals.console.error('Invalid call to Attr.set. Key ', key, ':: Value ', value, ':: Element ', dom)
			throw new Error('Attribute value was not simple')
		}
	}
	var set = function (element, key, value) {
		rawSet(element.dom(), key, value)
	}

	var fromHtml = function (html, scope) {
		var doc = scope || domGlobals.document
		var div = doc.createElement('div')
		div.innerHTML = html
		if (!div.hasChildNodes() || div.childNodes.length > 1) {
			domGlobals.console.error('HTML does not have a single root node', html)
			throw new Error('HTML must have a single root node')
		}
		return fromDom(div.childNodes[0])
	}
	var fromTag = function (tag, scope) {
		var doc = scope || domGlobals.document
		var node = doc.createElement(tag)
		return fromDom(node)
	}
	var fromText = function (text, scope) {
		var doc = scope || domGlobals.document
		var node = doc.createTextNode(text)
		return fromDom(node)
	}
	var fromDom = function (node) {
		if (node === null || node === undefined) {
			throw new Error('Node cannot be null or undefined')
		}
		return {dom: constant(node)}
	}
	var fromPoint = function (docElm, x, y) {
		var doc = docElm.dom()
		return Option.from(doc.elementFromPoint(x, y)).map(fromDom)
	}
	var Element = {
		fromHtml: fromHtml,
		fromTag: fromTag,
		fromText: fromText,
		fromDom: fromDom,
		fromPoint: fromPoint
	}

	var global$2 = tinymce.util.Tools.resolve('tinymce.dom.DOMUtils')

	var global$3 = tinymce.util.Tools.resolve('tinymce.util.Promise')

	var global$4 = tinymce.util.Tools.resolve('tinymce.util.XHR')

	var hasDimensions = function (editor) {
		return editor.getParam('image_dimensions', true, 'boolean')
	}
	var hasAdvTab = function (editor) {
		return editor.getParam('image_advtab', false, 'boolean')
	}
	var hasUploadTab = function (editor) {
		return editor.getParam('image_uploadtab', true, 'boolean')
	}
	var getPrependUrl = function (editor) {
		return editor.getParam('image_prepend_url', '', 'string')
	}
	var getClassList = function (editor) {
		return editor.getParam('image_class_list')
	}
	var hasDescription = function (editor) {
		return editor.getParam('image_description', true, 'boolean')
	}
	var hasImageTitle = function (editor) {
		return editor.getParam('image_title', false, 'boolean')
	}
	var hasImageCaption = function (editor) {
		return editor.getParam('image_caption', false, 'boolean')
	}
	var getImageList = function (editor) {
		return editor.getParam('image_list', false)
	}
	var hasUploadUrl = function (editor) {
		return !!getUploadUrl(editor)
	}
	var hasUploadHandler = function (editor) {
		return !!getUploadHandler(editor)
	}
	var getUploadUrl = function (editor) {
		return editor.getParam('images_upload_url', '', 'string')
	}
	var getUploadHandler = function (editor) {
		return editor.getParam('images_upload_handler', undefined, 'function')
	}
	var getUploadBasePath = function (editor) {
		return editor.getParam('images_upload_base_path', undefined, 'string')
	}
	var getUploadCredentials = function (editor) {
		return editor.getParam('images_upload_credentials', false, 'boolean')
	}
	var showAccessibilityOptions = function (editor) {
		return editor.getParam('a11y_advanced_options', false, 'boolean')
	}
	var isAutomaticUploadsEnabled = function (editor) {
		return editor.getParam('automatic_uploads', true, 'boolean')
	}
	var Settings = {
		hasDimensions: hasDimensions,
		hasUploadTab: hasUploadTab,
		hasAdvTab: hasAdvTab,
		getPrependUrl: getPrependUrl,
		getClassList: getClassList,
		hasDescription: hasDescription,
		hasImageTitle: hasImageTitle,
		hasImageCaption: hasImageCaption,
		getImageList: getImageList,
		hasUploadUrl: hasUploadUrl,
		hasUploadHandler: hasUploadHandler,
		getUploadUrl: getUploadUrl,
		getUploadHandler: getUploadHandler,
		getUploadBasePath: getUploadBasePath,
		getUploadCredentials: getUploadCredentials,
		showAccessibilityOptions: showAccessibilityOptions,
		isAutomaticUploadsEnabled: isAutomaticUploadsEnabled
	}

	var parseIntAndGetMax = function (val1, val2) {
		return Math.max(parseInt(val1, 10), parseInt(val2, 10))
	}
	var getImageSize = function (url, callback) {
		var img = domGlobals.document.createElement('img')
		var done = function (dimensions) {
			if (img.parentNode) {
				img.parentNode.removeChild(img)
			}
			callback(dimensions)
		}
		img.onload = function () {
			var width = parseIntAndGetMax(img.width, img.clientWidth)
			var height = parseIntAndGetMax(img.height, img.clientHeight)
			var dimensions = {
				width: width,
				height: height
			}
			done(Result.value(dimensions))
		}
		img.onerror = function () {
			done(Result.error('Failed to get image dimensions for: ' + url))
		}
		var style = img.style
		style.visibility = 'hidden'
		style.position = 'fixed'
		style.bottom = style.left = '0px'
		style.width = style.height = 'auto'
		domGlobals.document.body.appendChild(img)
		img.src = url
	}
	var removePixelSuffix = function (value) {
		if (value) {
			value = value.replace(/px$/, '')
		}
		return value
	}
	var addPixelSuffix = function (value) {
		if (value.length > 0 && /^[0-9]+$/.test(value)) {
			value += 'px'
		}
		return value
	}
	var mergeMargins = function (css) {
		if (css.margin) {
			var splitMargin = String(css.margin).split(' ')
			switch (splitMargin.length) {
				case 1:
					css['margin-top'] = css['margin-top'] || splitMargin[0]
					css['margin-right'] = css['margin-right'] || splitMargin[0]
					css['margin-bottom'] = css['margin-bottom'] || splitMargin[0]
					css['margin-left'] = css['margin-left'] || splitMargin[0]
					break
				case 2:
					css['margin-top'] = css['margin-top'] || splitMargin[0]
					css['margin-right'] = css['margin-right'] || splitMargin[1]
					css['margin-bottom'] = css['margin-bottom'] || splitMargin[0]
					css['margin-left'] = css['margin-left'] || splitMargin[1]
					break
				case 3:
					css['margin-top'] = css['margin-top'] || splitMargin[0]
					css['margin-right'] = css['margin-right'] || splitMargin[1]
					css['margin-bottom'] = css['margin-bottom'] || splitMargin[2]
					css['margin-left'] = css['margin-left'] || splitMargin[1]
					break
				case 4:
					css['margin-top'] = css['margin-top'] || splitMargin[0]
					css['margin-right'] = css['margin-right'] || splitMargin[1]
					css['margin-bottom'] = css['margin-bottom'] || splitMargin[2]
					css['margin-left'] = css['margin-left'] || splitMargin[3]
			}
			delete css.margin
		}
		return css
	}
	var createImageList = function (editor, callback) {
		var imageList = Settings.getImageList(editor)
		if (typeof imageList === 'string') {
			global$4.send({
				url: imageList,
				success: function (text) {
					callback(JSON.parse(text))
				}
			})
		} else if (typeof imageList === 'function') {
			imageList(callback)
		} else {
			callback(imageList)
		}
	}
	var waitLoadImage = function (editor, data, imgElm) {
		var selectImage = function () {
			imgElm.onload = imgElm.onerror = null
			if (editor.selection) {
				editor.selection.select(imgElm)
				editor.nodeChanged()
			}
		}
		imgElm.onload = function () {
			if (!data.width && !data.height && Settings.hasDimensions(editor)) {
				editor.dom.setAttribs(imgElm, {
					width: String(imgElm.clientWidth),
					height: String(imgElm.clientHeight)
				})
			}
			selectImage()
		}
		imgElm.onerror = selectImage
	}
	var blobToDataUri = function (blob) {
		return new global$3(function (resolve, reject) {
			var reader = new domGlobals.FileReader()
			reader.onload = function () {
				resolve(reader.result)
			}
			reader.onerror = function () {
				reject(reader.error.message)
			}
			reader.readAsDataURL(blob)
		})
	}
	var isPlaceholderImage = function (imgElm) {
		return imgElm.nodeName === 'IMG' && (imgElm.hasAttribute('data-mce-object') || imgElm.hasAttribute('data-mce-placeholder'))
	}
	var Utils = {
		getImageSize: getImageSize,
		removePixelSuffix: removePixelSuffix,
		addPixelSuffix: addPixelSuffix,
		mergeMargins: mergeMargins,
		createImageList: createImageList,
		waitLoadImage: waitLoadImage,
		blobToDataUri: blobToDataUri,
		isPlaceholderImage: isPlaceholderImage
	}

	var DOM = global$2.DOM
	var getHspace = function (image) {
		if (image.style.marginLeft && image.style.marginRight && image.style.marginLeft === image.style.marginRight) {
			return Utils.removePixelSuffix(image.style.marginLeft)
		} else {
			return ''
		}
	}
	var getVspace = function (image) {
		if (image.style.marginTop && image.style.marginBottom && image.style.marginTop === image.style.marginBottom) {
			return Utils.removePixelSuffix(image.style.marginTop)
		} else {
			return ''
		}
	}
	var getBorder = function (image) {
		if (image.style.borderWidth) {
			return Utils.removePixelSuffix(image.style.borderWidth)
		} else {
			return ''
		}
	}
	var getAttrib = function (image, name) {
		if (image.hasAttribute(name)) {
			return image.getAttribute(name)
		} else {
			return ''
		}
	}
	var getStyle = function (image, name) {
		return image.style[name] ? image.style[name] : ''
	}
	var hasCaption = function (image) {
		return image.parentNode !== null && image.parentNode.nodeName === 'FIGURE'
	}
	var setAttrib = function (image, name, value) {
		image.setAttribute(name, value)
	}
	var wrapInFigure = function (image) {
		var figureElm = DOM.create('figure', {class: 'image'})
		DOM.insertAfter(figureElm, image)
		figureElm.appendChild(image)
		figureElm.appendChild(DOM.create('figcaption', {contentEditable: 'true'}, 'Caption'))
		figureElm.contentEditable = 'false'
	}
	var removeFigure = function (image) {
		var figureElm = image.parentNode
		DOM.insertAfter(image, figureElm)
		DOM.remove(figureElm)
	}
	var toggleCaption = function (image) {
		if (hasCaption(image)) {
			removeFigure(image)
		} else {
			wrapInFigure(image)
		}
	}
	var normalizeStyle = function (image, normalizeCss) {
		var attrValue = image.getAttribute('style')
		var value = normalizeCss(attrValue !== null ? attrValue : '')
		if (value.length > 0) {
			image.setAttribute('style', value)
			image.setAttribute('data-mce-style', value)
		} else {
			image.removeAttribute('style')
		}
	}
	var setSize = function (name, normalizeCss) {
		return function (image, name, value) {
			if (image.style[name]) {
				image.style[name] = Utils.addPixelSuffix(value)
				normalizeStyle(image, normalizeCss)
			} else {
				setAttrib(image, name, value)
			}
		}
	}
	var getSize = function (image, name) {
		if (image.style[name]) {
			return Utils.removePixelSuffix(image.style[name])
		} else {
			return getAttrib(image, name)
		}
	}
	var setHspace = function (image, value) {
		var pxValue = Utils.addPixelSuffix(value)
		image.style.marginLeft = pxValue
		image.style.marginRight = pxValue
	}
	var setVspace = function (image, value) {
		var pxValue = Utils.addPixelSuffix(value)
		image.style.marginTop = pxValue
		image.style.marginBottom = pxValue
	}
	var setBorder = function (image, value) {
		var pxValue = Utils.addPixelSuffix(value)
		image.style.borderWidth = pxValue
	}
	var setBorderStyle = function (image, value) {
		image.style.borderStyle = value
	}
	var getBorderStyle = function (image) {
		return getStyle(image, 'borderStyle')
	}
	var isFigure = function (elm) {
		return elm.nodeName === 'FIGURE'
	}
	var isImage = function (elm) {
		return elm.nodeName === 'IMG'
	}
	var getIsDecorative = function (image) {
		return DOM.getAttrib(image, 'alt').length === 0 && DOM.getAttrib(image, 'role') === 'presentation'
	}
	var getAlt = function (image) {
		if (getIsDecorative(image)) {
			return ''
		} else {
			return getAttrib(image, 'alt')
		}
	}
	var defaultData = function () {
		return {
			src: '',
			alt: '',
			title: '',
			width: '',
			height: '',
			class: '',
			style: '',
			caption: false,
			hspace: '',
			vspace: '',
			border: '',
			borderStyle: '',
			isDecorative: false
		}
	}
	var getStyleValue = function (normalizeCss, data) {
		var image = domGlobals.document.createElement('img')
		setAttrib(image, 'style', data.style)
		if (getHspace(image) || data.hspace !== '') {
			setHspace(image, data.hspace)
		}
		if (getVspace(image) || data.vspace !== '') {
			setVspace(image, data.vspace)
		}
		if (getBorder(image) || data.border !== '') {
			setBorder(image, data.border)
		}
		if (getBorderStyle(image) || data.borderStyle !== '') {
			setBorderStyle(image, data.borderStyle)
		}
		return normalizeCss(image.getAttribute('style'))
	}
	var create = function (normalizeCss, data, info) {
		var image = domGlobals.document.createElement('img')
		write(normalizeCss, __assign(__assign({}, data), {caption: false}), image, info)
		setAlt(image, data.alt, data.isDecorative, info)
		if (data.caption) {
			var figure = DOM.create('figure', {class: 'image'})
			figure.appendChild(image)
			figure.appendChild(DOM.create('figcaption', {contentEditable: 'true'}, 'Caption'))
			figure.contentEditable = 'false'
			return figure
		} else {
			return image
		}
	}
	var read = function (normalizeCss, image) {
		return {
			src: getAttrib(image, 'src'),
			alt: getAlt(image),
			title: getAttrib(image, 'title'),
			width: getSize(image, 'width'),
			height: getSize(image, 'height'),
			class: getAttrib(image, 'class'),
			style: normalizeCss(getAttrib(image, 'style')),
			caption: hasCaption(image),
			hspace: getHspace(image),
			vspace: getVspace(image),
			border: getBorder(image),
			borderStyle: getStyle(image, 'borderStyle'),
			isDecorative: getIsDecorative(image)
		}
	}
	var updateProp = function (image, oldData, newData, name, set) {
		if (newData[name] !== oldData[name]) {
			set(image, name, newData[name])
		}
	}
	var setAlt = function (image, alt, isDecorative, info) {
		if (isDecorative) {
			DOM.setAttrib(image, 'role', 'presentation')
			let sugarImage = Element.fromDom(image)
			set(sugarImage, 'alt', '')
		} else {
			if (info.hasAccessibilityOptions) {
				DOM.setAttrib(image, 'alt', alt)
			} else {
				let sugarImage = Element.fromDom(image)
				set(sugarImage, 'alt', alt)
			}
			if (DOM.getAttrib(image, 'role') === 'presentation') {
				DOM.setAttrib(image, 'role', '')
			}
		}
	}
	var updateAlt = function (image, oldData, newData, info) {
		if (newData.alt !== oldData.alt || newData.isDecorative !== oldData.isDecorative) {
			setAlt(image, newData.alt, newData.isDecorative, info)
		}
	}
	var normalized = function (set, normalizeCss) {
		return function (image, name, value) {
			set(image, value)
			normalizeStyle(image, normalizeCss)
		}
	}
	var write = function (normalizeCss, newData, image, info) {
		var oldData = read(normalizeCss, image)
		updateProp(image, oldData, newData, 'caption', function (image, _name, _value) {
			console.log(_value)
			return toggleCaption(image)
		})
		updateProp(image, oldData, newData, 'src', setAttrib)
		updateProp(image, oldData, newData, 'title', setAttrib)
		updateProp(image, oldData, newData, 'width', setSize('width', normalizeCss))
		updateProp(image, oldData, newData, 'height', setSize('height', normalizeCss))
		updateProp(image, oldData, newData, 'class', setAttrib)
		updateProp(image, oldData, newData, 'style', normalized(function (image, value) {
			return setAttrib(image, 'style', value)
		}, normalizeCss))
		updateProp(image, oldData, newData, 'hspace', normalized(setHspace, normalizeCss))
		updateProp(image, oldData, newData, 'vspace', normalized(setVspace, normalizeCss))
		updateProp(image, oldData, newData, 'border', normalized(setBorder, normalizeCss))
		updateProp(image, oldData, newData, 'borderStyle', normalized(setBorderStyle, normalizeCss))
		updateAlt(image, oldData, newData, info)
	}

	var normalizeCss = function (editor, cssText) {
		var css = editor.dom.styles.parse(cssText)
		var mergedCss = Utils.mergeMargins(css)
		var compressed = editor.dom.styles.parse(editor.dom.styles.serialize(mergedCss))
		return editor.dom.styles.serialize(compressed)
	}
	var getSelectedImage = function (editor) {
		var imgElm = editor.selection.getNode()
		var figureElm = editor.dom.getParent(imgElm, 'figure.image')
		if (figureElm) {
			return editor.dom.select('img', figureElm)[0]
		}
		if (imgElm && (imgElm.nodeName !== 'IMG' || Utils.isPlaceholderImage(imgElm))) {
			return null
		}
		return imgElm
	}
	var splitTextBlock = function (editor, figure) {
		var dom = editor.dom
		var textBlock = dom.getParent(figure.parentNode, function (node) {
			return !!editor.schema.getTextBlockElements()[node.nodeName]
		}, editor.getBody())
		if (textBlock) {
			return dom.split(textBlock, figure)
		} else {
			return figure
		}
	}
	var readImageDataFromSelection = function (editor) {
		var image = getSelectedImage(editor)
		return image ? read(function (css) {
			return normalizeCss(editor, css)
		}, image) : defaultData()
	}
	var insertImageAtCaret = function (editor, data, info) {
		var elm = create(function (css) {
			return normalizeCss(editor, css)
		}, data, info)
		editor.dom.setAttrib(elm, 'data-mce-id', '__mcenew')
		editor.focus()
		editor.selection.setContent(elm.outerHTML)
		var insertedElm = editor.dom.select('*[data-mce-id="__mcenew"]')[0]
		editor.dom.setAttrib(insertedElm, 'data-mce-id', null)
		if (isFigure(insertedElm)) {
			var figure = splitTextBlock(editor, insertedElm)
			editor.selection.select(figure)
		} else {
			editor.selection.select(insertedElm)
		}
		// 设置最新的P标签 relative
		setParentPStyle(editor, insertedElm)
	}
	var syncSrcAttr = function (editor, image) {
		editor.dom.setAttrib(image, 'src', image.getAttribute('src'))
	}
	var deleteImage = function (editor, image) {
		if (image) {
			var elm = editor.dom.is(image.parentNode, 'figure.image') ? image.parentNode : image
			editor.dom.remove(elm)
			editor.focus()
			editor.nodeChanged()
			if (editor.dom.isEmpty(editor.getBody())) {
				editor.setContent('')
				editor.selection.setCursorLocation()
			}
		}
	}
	var writeImageDataToSelection = function (editor, data, info) {
		var image = getSelectedImage(editor)
		write(function (css) {
			return normalizeCss(editor, css)
		}, data, image, info)
		syncSrcAttr(editor, image)
		if (isFigure(image.parentNode)) {
			var figure = image.parentNode
			splitTextBlock(editor, figure)
			editor.selection.select(image.parentNode)
		} else {
			editor.selection.select(image)
			Utils.waitLoadImage(editor, data, image)
		}
	}
	var insertOrUpdateImage = function (editor, data, info) {
		var image = getSelectedImage(editor)
		if (image) {
			if (data.src) {
				writeImageDataToSelection(editor, data, info)
			} else {
				deleteImage(editor, image)
			}
		} else if (data.src) {
			insertImageAtCaret(editor, data, info)
		}
	}

	var global$5 = tinymce.util.Tools.resolve('tinymce.util.Tools')

	var getValue = function (item) {
		return isString(item.value) ? item.value : ''
	}
	var sanitizeList = function (list, extractValue) {
		var out = []
		global$5.each(list, function (item) {
			var text = isString(item.text) ? item.text : isString(item.title) ? item.title : ''
			if (item.menu !== undefined) {
				var items = sanitizeList(item.menu, extractValue)
				out.push({
					text: text,
					items: items
				})
			} else {
				var value = extractValue(item)
				out.push({
					text: text,
					value: value
				})
			}
		})
		return out
	}
	var sanitizer = function (extracter) {
		if (extracter === void 0) {
			extracter = getValue
		}
		return function (list) {
			if (list) {
				return Option.from(list).map(function (list) {
					return sanitizeList(list, extracter)
				})
			} else {
				return Option.none()
			}
		}
	}
	var sanitize = function (list) {
		return sanitizer(getValue)(list)
	}
	var isGroup = function (item) {
		return Object.prototype.hasOwnProperty.call(item, 'items')
	}
	var findEntryDelegate = function (list, value) {
		return findMap(list, function (item) {
			if (isGroup(item)) {
				return findEntryDelegate(item.items, value)
			} else if (item.value === value) {
				return Option.some(item)
			} else {
				return Option.none()
			}
		})
	}
	var findEntry = function (optList, value) {
		return optList.bind(function (list) {
			return findEntryDelegate(list, value)
		})
	}
	var ListUtils = {
		sanitizer: sanitizer,
		sanitize: sanitize,
		findEntry: findEntry
	}

	var pathJoin = function (path1, path2) {
		if (path1) {
			return path1.replace(/\/$/, '') + '/' + path2.replace(/^\//, '')
		}
		return path2
	}

	function Uploader(settings) {
		var defaultHandler = function (blobInfo, success, failure, progress) {
			var xhr, formData
			xhr = new domGlobals.XMLHttpRequest()
			xhr.open('POST', settings.url)
			xhr.withCredentials = settings.credentials
			xhr.upload.onprogress = function (e) {
				progress(e.loaded / e.total * 100)
			}
			xhr.onerror = function () {
				failure('Image upload failed due to a XHR Transport error. Code: ' + xhr.status)
			}
			xhr.onload = function () {
				var json
				if (xhr.status < 200 || xhr.status >= 300) {
					failure('HTTP Error: ' + xhr.status)
					return
				}
				json = JSON.parse(xhr.responseText)
				if (!json || typeof json.location !== 'string') {
					failure('Invalid JSON: ' + xhr.responseText)
					return
				}
				success(pathJoin(settings.basePath, json.location))
			}
			formData = new domGlobals.FormData()
			formData.append('file', blobInfo.blob(), blobInfo.filename())
			xhr.send(formData)
		}
		var uploadBlob = function (blobInfo, handler) {
			return new global$3(function (resolve, reject) {
				try {
					handler(blobInfo, resolve, reject, noop)
				} catch (ex) {
					reject(ex.message)
				}
			})
		}
		var isDefaultHandler = function (handler) {
			return handler === defaultHandler
		}
		var upload = function (blobInfo) {
			return !settings.url && isDefaultHandler(settings.handler) ? global$3.reject('Upload url missing from the settings.') : uploadBlob(blobInfo, settings.handler)
		}
		settings = global$5.extend({
			credentials: false,
			handler: defaultHandler
		}, settings)
		return {upload: upload}
	}

	var makeTab = function (info) {
		console.log(info)
		return {
			title: 'Advanced',
			name: 'advanced',
			items: [
				{
					type: 'input',
					label: 'Style',
					name: 'style'
				},
				{
					type: 'grid',
					columns: 2,
					items: [
						{
							type: 'input',
							label: 'Vertical space',
							name: 'vspace',
							inputMode: 'numeric'
						},
						{
							type: 'input',
							label: 'Horizontal space',
							name: 'hspace',
							inputMode: 'numeric'
						},
						{
							type: 'input',
							label: 'Border width',
							name: 'border',
							inputMode: 'numeric'
						},
						{
							type: 'selectbox',
							name: 'borderstyle',
							label: 'Border style',
							items: [
								{
									text: 'Select...',
									value: ''
								},
								{
									text: 'Solid',
									value: 'solid'
								},
								{
									text: 'Dotted',
									value: 'dotted'
								},
								{
									text: 'Dashed',
									value: 'dashed'
								},
								{
									text: 'Double',
									value: 'double'
								},
								{
									text: 'Groove',
									value: 'groove'
								},
								{
									text: 'Ridge',
									value: 'ridge'
								},
								{
									text: 'Inset',
									value: 'inset'
								},
								{
									text: 'Outset',
									value: 'outset'
								},
								{
									text: 'None',
									value: 'none'
								},
								{
									text: 'Hidden',
									value: 'hidden'
								}
							]
						}
					]
				}
			]
		}
	}
	var AdvTab = {makeTab: makeTab}

	var collect = function (editor) {
		var urlListSanitizer = ListUtils.sanitizer(function (item) {
			return editor.convertURL(item.value || item.url, 'src')
		})
		var futureImageList = Future.nu(function (completer) {
			Utils.createImageList(editor, function (imageList) {
				completer(urlListSanitizer(imageList).map(function (items) {
					return flatten([
						[{
							text: 'None',
							value: ''
						}],
						items
					])
				}))
			})
		})
		var classList = ListUtils.sanitize(Settings.getClassList(editor))
		var hasAdvTab = Settings.hasAdvTab(editor)
		var hasUploadTab = Settings.hasUploadTab(editor)
		var hasUploadUrl = Settings.hasUploadUrl(editor)
		var hasUploadHandler = Settings.hasUploadHandler(editor)
		var image = readImageDataFromSelection(editor)
		var hasDescription = Settings.hasDescription(editor)
		var hasImageTitle = Settings.hasImageTitle(editor)
		var hasDimensions = Settings.hasDimensions(editor)
		var hasImageCaption = Settings.hasImageCaption(editor)
		var hasAccessibilityOptions = Settings.showAccessibilityOptions(editor)
		var url = Settings.getUploadUrl(editor)
		var basePath = Settings.getUploadBasePath(editor)
		var credentials = Settings.getUploadCredentials(editor)
		var handler = Settings.getUploadHandler(editor)
		var automaticUploads = Settings.isAutomaticUploadsEnabled(editor)
		var prependURL = Option.some(Settings.getPrependUrl(editor)).filter(function (preUrl) {
			return isString(preUrl) && preUrl.length > 0
		})
		return futureImageList.map(function (imageList) {
			return {
				image: image,
				imageList: imageList,
				classList: classList,
				hasAdvTab: hasAdvTab,
				hasUploadTab: hasUploadTab,
				hasUploadUrl: hasUploadUrl,
				hasUploadHandler: hasUploadHandler,
				hasDescription: hasDescription,
				hasImageTitle: hasImageTitle,
				hasDimensions: hasDimensions,
				hasImageCaption: hasImageCaption,
				url: url,
				basePath: basePath,
				credentials: credentials,
				handler: handler,
				prependURL: prependURL,
				hasAccessibilityOptions: hasAccessibilityOptions,
				automaticUploads: automaticUploads
			}
		})
	}

	var makeItems = function (info) {
		var imageUrl = {
			name: 'src',
			type: 'urlinput',
			filetype: 'image',
			label: 'Source'
		}
		var imageList = info.imageList.map(function (items) {
			return {
				name: 'images',
				type: 'selectbox',
				label: 'Image list',
				items: items
			}
		})
		var imageDescription = {
			name: 'alt',
			type: 'input',
			label: 'Alternative description',
			disabled: info.hasAccessibilityOptions && info.image.isDecorative
		}
		var imageTitle = {
			name: 'title',
			type: 'input',
			label: 'Image title'
		}
		var imageDimensions = {
			name: 'dimensions',
			type: 'sizeinput'
		}
		var isDecorative = {
			type: 'label',
			label: 'Accessibility',
			items: [{
				name: 'isDecorative',
				type: 'checkbox',
				label: 'Image is decorative'
			}]
		}
		var classList = info.classList.map(function (items) {
			return {
				name: 'classes',
				type: 'selectbox',
				label: 'Class',
				items: items
			}
		})
		var caption = {
			type: 'label',
			label: 'Caption',
			items: [{
				type: 'checkbox',
				name: 'caption',
				label: 'Show caption'
			}]
		}
		return flatten([
			[imageUrl],
			imageList.toArray(),
			info.hasAccessibilityOptions && info.hasDescription ? [isDecorative] : [],
			info.hasDescription ? [imageDescription] : [],
			info.hasImageTitle ? [imageTitle] : [],
			info.hasDimensions ? [imageDimensions] : [],
			[{
				type: 'grid',
				columns: 2,
				items: flatten([
					classList.toArray(),
					info.hasImageCaption ? [caption] : []
				])
			}]
		])
	}
	var makeTab$1 = function (info) {
		return {
			title: 'General',
			name: 'general',
			items: makeItems(info)
		}
	}
	var MainTab = {
		makeTab: makeTab$1,
		makeItems: makeItems
	}

	var makeTab$2 = function (info) {
		console.log(info)
		var items = [{
			type: 'dropzone',
			name: 'fileinput'
		}]
		return {
			title: 'Upload',
			name: 'upload',
			items: items
		}
	}
	var UploadTab = {makeTab: makeTab$2}

	var createState = function (info) {
		return {
			prevImage: ListUtils.findEntry(info.imageList, info.image.src),
			prevAlt: info.image.alt,
			open: true
		}
	}
	var fromImageData = function (image) {
		return {
			src: {
				value: image.src,
				meta: {}
			},
			images: image.src,
			alt: image.alt,
			title: image.title,
			dimensions: {
				width: image.width,
				height: image.height
			},
			classes: image.class,
			caption: image.caption,
			style: image.style,
			vspace: image.vspace,
			border: image.border,
			hspace: image.hspace,
			borderstyle: image.borderStyle,
			fileinput: [],
			isDecorative: image.isDecorative
		}
	}
	var toImageData = function (data) {
		return {
			src: data.src.value,
			alt: data.alt,
			title: data.title,
			width: data.dimensions.width,
			height: data.dimensions.height,
			class: data.classes,
			style: data.style,
			caption: data.caption,
			hspace: data.hspace,
			vspace: data.vspace,
			border: data.border,
			borderStyle: data.borderstyle,
			isDecorative: data.isDecorative
		}
	}
	var addPrependUrl2 = function (info, srcURL) {
		if (!/^(?:[a-zA-Z]+:)?\/\//.test(srcURL)) {
			return info.prependURL.bind(function (prependUrl) {
				if (srcURL.substring(0, prependUrl.length) !== prependUrl) {
					return Option.some(prependUrl + srcURL)
				}
				return Option.none()
			})
		}
		return Option.none()
	}
	var addPrependUrl = function (info, api) {
		var data = api.getData()
		addPrependUrl2(info, data.src.value).each(function (srcURL) {
			api.setData({
				src: {
					value: srcURL,
					meta: data.src.meta
				}
			})
		})
	}
	var formFillFromMeta2 = function (info, data, meta) {
		if (info.hasDescription && isString(meta.alt)) {
			data.alt = meta.alt
		}
		if (info.hasAccessibilityOptions) {
			data.isDecorative = meta.isDecorative || false
		}
		if (info.hasImageTitle && isString(meta.title)) {
			data.title = meta.title
		}
		if (info.hasDimensions) {
			if (isString(meta.width)) {
				data.dimensions.width = meta.width
			}
			if (isString(meta.height)) {
				data.dimensions.height = meta.height
			}
		}
		if (isString(meta.class)) {
			ListUtils.findEntry(info.classList, meta.class).each(function (entry) {
				data.classes = entry.value
			})
		}
		if (info.hasImageCaption) {
			if (isBoolean(meta.caption)) {
				data.caption = meta.caption
			}
		}
		if (info.hasAdvTab) {
			if (isString(meta.style)) {
				data.style = meta.style
			}
			if (isString(meta.vspace)) {
				data.vspace = meta.vspace
			}
			if (isString(meta.border)) {
				data.border = meta.border
			}
			if (isString(meta.hspace)) {
				data.hspace = meta.hspace
			}
			if (isString(meta.borderstyle)) {
				data.borderstyle = meta.borderstyle
			}
		}
	}
	var formFillFromMeta = function (info, api) {
		var data = api.getData()
		var meta = data.src.meta
		if (meta !== undefined) {
			var newData = deepMerge({}, data)
			formFillFromMeta2(info, newData, meta)
			api.setData(newData)
		}
	}
	var calculateImageSize = function (helpers, info, state, api) {
		var data = api.getData()
		var url = data.src.value
		var meta = data.src.meta || {}
		if (!meta.width && !meta.height && info.hasDimensions) {
			helpers.imageSize(url).get(function (result) {
				result.each(function (size) {
					if (state.open) {
						api.setData({dimensions: size})
					}
				})
			})
		}
	}
	var updateImagesDropdown = function (info, state, api) {
		var data = api.getData()
		var image = ListUtils.findEntry(info.imageList, data.src.value)
		state.prevImage = image
		api.setData({
			images: image.map(function (entry) {
				return entry.value
			}).getOr('')
		})
	}
	var changeSrc = function (helpers, info, state, api) {
		addPrependUrl(info, api)
		formFillFromMeta(info, api)
		calculateImageSize(helpers, info, state, api)
		updateImagesDropdown(info, state, api)
	}
	var changeImages = function (helpers, info, state, api) {
		var data = api.getData()
		var image = ListUtils.findEntry(info.imageList, data.images)
		image.each(function (img) {
			var updateAlt = data.alt === '' || state.prevImage.map(function (image) {
				return image.text === data.alt
			}).getOr(false)
			if (updateAlt) {
				if (img.value === '') {
					api.setData({
						src: img,
						alt: state.prevAlt
					})
				} else {
					api.setData({
						src: img,
						alt: img.text
					})
				}
			} else {
				api.setData({src: img})
			}
		})
		state.prevImage = image
		changeSrc(helpers, info, state, api)
	}
	var calcVSpace = function (css) {
		var matchingTopBottom = css['margin-top'] && css['margin-bottom'] && css['margin-top'] === css['margin-bottom']
		return matchingTopBottom ? Utils.removePixelSuffix(String(css['margin-top'])) : ''
	}
	var calcHSpace = function (css) {
		var matchingLeftRight = css['margin-right'] && css['margin-left'] && css['margin-right'] === css['margin-left']
		return matchingLeftRight ? Utils.removePixelSuffix(String(css['margin-right'])) : ''
	}
	var calcBorderWidth = function (css) {
		return css['border-width'] ? Utils.removePixelSuffix(String(css['border-width'])) : ''
	}
	var calcBorderStyle = function (css) {
		return css['border-style'] ? String(css['border-style']) : ''
	}
	var calcStyle = function (parseStyle, serializeStyle, css) {
		return serializeStyle(parseStyle(serializeStyle(css)))
	}
	var changeStyle2 = function (parseStyle, serializeStyle, data) {
		var css = Utils.mergeMargins(parseStyle(data.style))
		var dataCopy = deepMerge({}, data)
		dataCopy.vspace = calcVSpace(css)
		dataCopy.hspace = calcHSpace(css)
		dataCopy.border = calcBorderWidth(css)
		dataCopy.borderstyle = calcBorderStyle(css)
		dataCopy.style = calcStyle(parseStyle, serializeStyle, css)
		return dataCopy
	}
	var changeStyle = function (helpers, api) {
		var data = api.getData()
		var newData = changeStyle2(helpers.parseStyle, helpers.serializeStyle, data)
		api.setData(newData)
	}
	var changeAStyle = function (helpers, info, api) {
		var data = deepMerge(fromImageData(info.image), api.getData())
		var style = getStyleValue(helpers.normalizeCss, toImageData(data))
		api.setData({style: style})
	}
	var changeFileInput = function (helpers, info, state, api) {
		var data = api.getData()
		api.block('Uploading image')
		head(data.fileinput).fold(function () {
			api.unblock()
		}, function (file) {
			var blobUri = domGlobals.URL.createObjectURL(file)
			var uploader = Uploader({
				url: info.url,
				basePath: info.basePath,
				credentials: info.credentials,
				handler: info.handler
			})
			var finalize = function () {
				api.unblock()
				domGlobals.URL.revokeObjectURL(blobUri)
			}
			var updateSrcAndSwitchTab = function (url) {
				api.setData({
					src: {
						value: url,
						meta: {}
					}
				})
				api.showTab('general')
				changeSrc(helpers, info, state, api)
			}
			Utils.blobToDataUri(file).then(function (dataUrl) {
				var blobInfo = helpers.createBlobCache(file, blobUri, dataUrl)
				if (info.automaticUploads) {
					uploader.upload(blobInfo).then(function (url) {
						updateSrcAndSwitchTab(url)
						finalize()
					}).catch(function (err) {
						finalize()
						helpers.alertErr(api, err)
					})
				} else {
					helpers.addToBlobCache(blobInfo)
					updateSrcAndSwitchTab(blobInfo.blobUri())
					api.unblock()
				}
			})
		})
	}
	var changeHandler = function (helpers, info, state) {
		return function (api, evt) {
			if (evt.name === 'src') {
				changeSrc(helpers, info, state, api)
			} else if (evt.name === 'images') {
				changeImages(helpers, info, state, api)
			} else if (evt.name === 'alt') {
				state.prevAlt = api.getData().alt
			} else if (evt.name === 'style') {
				changeStyle(helpers, api)
			} else if (evt.name === 'vspace' || evt.name === 'hspace' || evt.name === 'border' || evt.name === 'borderstyle') {
				changeAStyle(helpers, info, api)
			} else if (evt.name === 'fileinput') {
				changeFileInput(helpers, info, state, api)
			} else if (evt.name === 'isDecorative') {
				if (api.getData().isDecorative) {
					api.disable('alt')
				} else {
					api.enable('alt')
				}
			}
		}
	}
	var closeHandler = function (state) {
		return function () {
			state.open = false
		}
	}
	var makeDialogBody = function (info) {
		if (info.hasAdvTab || info.hasUploadUrl || info.hasUploadHandler) {
			var tabPanel = {
				type: 'tabpanel',
				tabs: flatten([
					[MainTab.makeTab(info)],
					info.hasAdvTab ? [AdvTab.makeTab(info)] : [],
					info.hasUploadTab && (info.hasUploadUrl || info.hasUploadHandler) ? [UploadTab.makeTab(info)] : []
				])
			}
			return tabPanel
		} else {
			var panel = {
				type: 'panel',
				items: MainTab.makeItems(info)
			}
			return panel
		}
	}
	var makeDialog = function (helpers) {
		return function (info) {
			var state = createState(info)
			return {
				title: 'Insert/Edit Image',
				size: 'normal',
				body: makeDialogBody(info),
				buttons: [
					{
						type: 'cancel',
						name: 'cancel',
						text: 'Cancel'
					},
					{
						type: 'submit',
						name: 'save',
						text: 'Save',
						primary: true
					}
				],
				initialData: fromImageData(info.image),
				onSubmit: helpers.onSubmit(info),
				onChange: changeHandler(helpers, info, state),
				onClose: closeHandler(state)
			}
		}
	}
	var submitHandler = function (editor) {
		return function (info) {
			return function (api) {
				var data = deepMerge(fromImageData(info.image), api.getData())
				editor.undoManager.transact(function () {
					insertOrUpdateImage(editor, toImageData(data), info)
				})
				editor.editorUpload.uploadImagesAuto()
				api.close()
			}
		}
	}
	var imageSize = function (editor) {
		return function (url) {
			return FutureResult.nu(function (completer) {
				Utils.getImageSize(editor.documentBaseURI.toAbsolute(url), function (data) {
					var result = data.map(function (dimensions) {
						return {
							width: String(dimensions.width),
							height: String(dimensions.height)
						}
					})
					completer(result)
				})
			})
		}
	}
	var createBlobCache = function (editor) {
		return function (file, blobUri, dataUrl) {
			return editor.editorUpload.blobCache.create({
				blob: file,
				blobUri: blobUri,
				name: file.name ? file.name.replace(/\.[^.]+$/, '') : null,
				base64: dataUrl.split(',')[1]
			})
		}
	}
	var addToBlobCache = function (editor) {
		return function (blobInfo) {
			editor.editorUpload.blobCache.add(blobInfo)
		}
	}
	var alertErr = function (editor) {
		return function (api, message) {
			editor.windowManager.alert(message, api.close)
		}
	}
	var normalizeCss$1 = function (editor) {
		return function (cssText) {
			return normalizeCss(editor, cssText)
		}
	}
	var parseStyle = function (editor) {
		return function (cssText) {
			return editor.dom.parseStyle(cssText)
		}
	}
	var serializeStyle = function (editor) {
		return function (stylesArg, name) {
			return editor.dom.serializeStyle(stylesArg, name)
		}
	}
	var Dialog = function (editor) {
		var helpers = {
			onSubmit: submitHandler(editor),
			imageSize: imageSize(editor),
			addToBlobCache: addToBlobCache(editor),
			createBlobCache: createBlobCache(editor),
			alertErr: alertErr(editor),
			normalizeCss: normalizeCss$1(editor),
			parseStyle: parseStyle(editor),
			serializeStyle: serializeStyle(editor)
		}
		var open = function () {
			return collect(editor).map(makeDialog(helpers)).get(function (spec) {
				editor.windowManager.open(spec)
			})
		}
		return {open: open}
	}

	var register = function (editor) {
		editor.addCommand('mceSignature', Dialog(editor).open)
	}
	var Commands = {register: register}

	var hasImageClass = function (node) {
		var className = node.attr('class')
		return className && /\bimage\b/.test(className)
	}
	var toggleContentEditableState = function (state) {
		return function (nodes) {
			var i = nodes.length
			var toggleContentEditable = function (node) {
				node.attr('contenteditable', state ? 'true' : null)
			}
			while (i--) {
				var node = nodes[i]
				if (hasImageClass(node)) {
					node.attr('contenteditable', state ? 'false' : null)
					global$5.each(node.getAll('figcaption'), toggleContentEditable)
				}
			}
		}
	}
	var setup = function (editor) {
		editor.on('PreInit', function () {
			editor.parser.addNodeFilter('figure', toggleContentEditableState(true))
			editor.serializer.addNodeFilter('figure', toggleContentEditableState(false))
		})
	}
	var FilterContent = {setup: setup}

	// 这是父元素样式
	var setParentPStyle = function (editor, elm) {
		const parentP = editor.dom.getParent(elm, 'p')
		if (parentP) {
			editor.dom.setStyle(parentP, 'position', 'relative')
		}
	}

	var register$1 = function (editor) {
		editor.ui.registry.addToggleButton('signature', {
			icon: 'template',
			tooltip: '印章',
			onAction: Dialog(editor).open,
			onSetup: function (buttonApi) {
				return editor.selection.selectorChangedWithUnbind('img:not([data-mce-object],[data-mce-placeholder]),figure.image', buttonApi.setActive).unbind
			}
		})
		editor.ui.registry.addMenuItem('signature', {
			icon: 'template',
			text: 'Image...',
			onAction: Dialog(editor).open
		})

		// 图标 https://www.tiny.cloud/docs/tinymce/6/editor-icon-identifiers/
		editor.ui.registry.addToggleButton('signature-left', {
			icon: 'chevron-left',
			tooltip: '印章左移',
			onAction: function () {
				var image = getSelectedImage(editor)
				if (image && image.nodeName === 'IMG') {
					// image.style.position = 'absolute'
					// image.style.zIndex = 1
					// image.style.left = `${parseInt(left || 0) - 10}px`
					const left = image.style.left === 'auto' ? 0 : image.style.left
					editor.dom.setStyle(image, 'position', 'absolute')
					editor.dom.setStyle(image, 'z-index', 1)
					editor.dom.setStyle(image, 'left', `${parseInt(left || 0) - 10}px`)

					setParentPStyle(editor, image)
				}
			}
		})

		editor.ui.registry.addToggleButton('signature-right', {
			icon: 'chevron-right',
			tooltip: '印章右移',
			onAction: function () {
				var image = getSelectedImage(editor)
				if (image && image.nodeName === 'IMG') {
					// image.style.position = 'absolute'
					// image.style.zIndex = 1
					// image.style.left = `${parseInt(left || 0) + 10}px`
					const left = image.style.left === 'auto' ? 0 : image.style.left
					editor.dom.setStyle(image, 'position', 'absolute')
					editor.dom.setStyle(image, 'z-index', 1)
					editor.dom.setStyle(image, 'left', `${parseInt(left || 0) + 10}px`)

					setParentPStyle(editor, image)
				}
			}
		})

		editor.ui.registry.addToggleButton('signature-top', {
			icon: 'chevron-up',
			tooltip: '印章上移',
			onAction: function () {
				var image = getSelectedImage(editor)
				console.log(image.style)
				if (image && image.nodeName === 'IMG') {
					// image.style.position = 'absolute'
					// image.style.zIndex = 1
					// image.style.top = `${parseInt(top || 0) - 10}px`

					const top = image.style.top === 'auto' ? 0 : image.style.top
					editor.dom.setStyle(image, 'position', 'absolute')
					editor.dom.setStyle(image, 'z-index', 1)
					editor.dom.setStyle(image, 'top', `${parseInt(top || 0) - 10}px`)

					setParentPStyle(editor, image)
				}
			}
		})

		editor.ui.registry.addToggleButton('signature-bottom', {
			icon: 'chevron-down',
			tooltip: '印章下移',
			onAction: function () {
				var image = getSelectedImage(editor)
				if (image && image.nodeName === 'IMG') {
					// image.style.position = 'absolute'
					// image.style.zIndex = 1
					// image.style.top = `${parseInt(top || 0) + 10}px`

					const top = image.style.top === 'auto' ? 0 : image.style.top
					editor.dom.setStyle(image, 'position', 'absolute')
					editor.dom.setStyle(image, 'z-index', 1)
					editor.dom.setStyle(image, 'top', `${parseInt(top || 0) + 10}px`)

					setParentPStyle(editor, image)
				}
			}
		})

		editor.ui.registry.addContextMenu('signature', {
			update: function (element) {
				return isFigure(element) || isImage(element) && !Utils.isPlaceholderImage(element) ? ['image'] : []
			}
		})
	}
	var Buttons = {register: register$1}

	function Plugin() {
		global$1.add('signature', function (editor) {
			FilterContent.setup(editor)
			Buttons.register(editor)
			Commands.register(editor)
		})
	}

	Plugin()
}(window))
